﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace Battle.View
{
    public enum BuffParticleType
    {
        EFFECT_ON,          // 上BUFF特效
        EFFECT_OFF,         // 下BUFF特效
        EFFECT_HIT,         // BUFF被击特效
        EFFECT_LAST,        // BUFF持续特效
    }

    public class BattleBuffer : IBattleInst
    {
        public BufferResourceCache bufferResourceCache
        {
            get
            {
                return BattleViewCtrl.GetInstance().bufferResourceCache;
            }
        }

        public string uniqueId;
        string buffId;
        string _iconName;
        public string iconName
        {
            get
            {
                return _iconName;
            }
        }
        bool _isStun;
        public bool isStun
        {
            get
            {
                return _isStun;
            }
        }
        Dict.DataModel.TableBuff tableBuff;

        BattleCharacter mounter;

        ParticleObj buffOnObj;
        ParticleObj buffOffObj;
        ParticleObj buffLastObj;

        public void Init(object data)
        {
            ProtoBuf.Message.Buffer buffData = data as ProtoBuf.Message.Buffer;
            if (buffData != null)
            {
                uniqueId = buffData.uid;
                buffId = buffData.bufferId;
                tableBuff = Dict.Blo.DictBuffBlo.GetTableBuff(buffId);
                _iconName = tableBuff.BuffIconName;
                _isStun = tableBuff.Factor == Dict.Config.TableFactorConst.dizzy;
                buffOnObj = null;
                buffOffObj = null;
                buffLastObj = null;
                mounter = BattleViewCtrl.GetInstance().GetBattleCharacter(buffData.targetUid);
                mounter.AddBuff(this);
            }
        }

        public void Load()
        {
            bufferResourceCache.AddBuffer(buffId);
        }

        public void Run()
        {
            BattleViewCtrl.GetInstance().StartCoroutine(_Run());
        }

        IEnumerator _Run()
        {
            Load();
            while (!bufferResourceCache.IsBufferLoaded(buffId))
            {
                yield return null;
            }
            if (IsBuffParticleExist(BuffParticleType.EFFECT_ON) && buffOnObj == null)
            {
                buffOnObj = ParticleFactory.CreateParticleObj(GetBuffParticleData(BuffParticleType.EFFECT_ON));
            }
            if (IsBuffParticleExist(BuffParticleType.EFFECT_LAST) && buffLastObj == null)
            {
                buffLastObj = ParticleFactory.CreateParticleObj(GetBuffParticleData(BuffParticleType.EFFECT_LAST));
            }
            if (buffOnObj != null)
            {
                PlayBuffParticle(GetBuffParticleData(BuffParticleType.EFFECT_ON), buffOnObj);
            }
            if (buffLastObj != null)
            {
                PlayBuffParticle(GetBuffParticleData(BuffParticleType.EFFECT_LAST), buffLastObj, false);
            }
        }

        public void Stop()
        {
            if (IsBuffParticleExist(BuffParticleType.EFFECT_OFF) && buffOffObj == null)
            {
                buffOffObj = ParticleFactory.CreateParticleObj(GetBuffParticleData(BuffParticleType.EFFECT_OFF));
            }
            if (buffOffObj != null)
            {
                PlayBuffParticle(GetBuffParticleData(BuffParticleType.EFFECT_OFF), buffOffObj);
            }
            
            Unload();
            mounter.RemoveBuff(this);
        }

        public void Tick()
        {
        }

        public void Unload()
        {
            BattleViewCtrl.GetInstance().StartCoroutine(_Unload());
        }

        IEnumerator _Unload()
        {
            if (buffLastObj != null)
            {
                buffLastObj.Recycle();
            }
            while (buffOffObj != null && buffOffObj.IsPlaying())
            {
                yield return null;
            }
            if (buffOnObj != null)
            {
                buffOnObj.Recycle();
            }
            if (buffOffObj != null)
            {
                buffOffObj.Recycle();
            }
            if (buffLastObj != null)
            {
                buffLastObj.Recycle();
            }
            bufferResourceCache.RemoveBuffer(buffId);
        }

        void PlayBuffHitParticle(ParticleData pd, ParticleObj obj)
        {
            PlayBuffParticle(pd, obj, true);
        }

        void PlayBuffParticle(ParticleData pd, ParticleObj obj, bool isAutoRecovery = true)
        {
            if (pd.pt == ParticleType.BIND_BONE)
            {
                Transform trans = null;
                trans = mounter.GetBindTransform(pd.bindBone); 
                if (trans == null)
                {
                    trans = mounter.transform;
                }
                obj.Play(LayerName.SceneParticle, trans, Vector3.zero, mounter.particleScale, Vector3.zero, isAutoRecovery);
                if (mounter.GetCurrrentStateType() != ActorState.Ultimate && mounter.GetCurrrentStateType() != ActorState.Ultimate)
                {
                    obj.Show();
                }
                else
                {
                    obj.Hide();
                }
            }
        }

        public void OnHit(out bool isPlay)
        {
            isPlay = false;
            if (IsBuffParticleExist(BuffParticleType.EFFECT_HIT) && bufferResourceCache.IsBufferLoaded(buffId))
            {
                var particleObj = ParticleFactory.CreateParticleObj(GetBuffParticleData(BuffParticleType.EFFECT_HIT));
                PlayBuffHitParticle(GetBuffParticleData(BuffParticleType.EFFECT_HIT), particleObj);
                isPlay = true;
            }
        }

        public void OnEnterUltimate()
        {
            if (buffOnObj != null)
            {
                buffOnObj.Hide();
            }
            if (buffOffObj != null)
            {
                buffOffObj.Hide();
            }
            if (buffLastObj != null)
            {
                buffLastObj.Hide();
            }
        }

        public void OnLeaveUltimate()
        {
            if (buffLastObj != null)
            {
                buffLastObj.Show();
            }
        }

        ParticleData GetBuffParticleData(BuffParticleType t)
        {
            switch (t)
            {
                case BuffParticleType.EFFECT_ON:
                    if (_buffOnData == null)
                    {
                        _buffOnData = ParticleData.CreateParticleData(tableBuff.EffectOn, tableBuff.EffectOnBone);
                    }
                    return _buffOnData;
                case BuffParticleType.EFFECT_OFF:
                    if (_buffOffData == null)
                    {
                        _buffOffData = ParticleData.CreateParticleData(tableBuff.EffectOff, tableBuff.EffectOffBone);
                    }
                    return _buffOffData;
                case BuffParticleType.EFFECT_HIT:
                    if (_buffHitData == null)
                    {
                        _buffHitData = ParticleData.CreateParticleData(tableBuff.HitEffect, tableBuff.HitEffectBone);
                    }
                    return _buffHitData;
                case BuffParticleType.EFFECT_LAST:
                    if (_buffLastData == null)
                    {
                        _buffLastData = ParticleData.CreateParticleData(tableBuff.LastEffect, tableBuff.LastEffectBone);
                    }
                    return _buffLastData;
                default:
                    return null;
            }
        }

        ParticleData _buffOnData;
        ParticleData _buffOffData;
        ParticleData _buffLastData;
        ParticleData _buffHitData;

        bool IsBuffParticleExist(BuffParticleType t)
        {
            switch (t)
            {
                case BuffParticleType.EFFECT_ON:
                    return IsBuffHasEffectOn();
                case BuffParticleType.EFFECT_OFF:
                    return IsBuffHasEffectOff();
                case BuffParticleType.EFFECT_HIT:
                    return IsBuffHasEffectHit();
                case BuffParticleType.EFFECT_LAST:
                    return IsBuffHasEffectLast();
                default:
                    return false;
            }
        }

        bool IsBuffHasEffectOn()
        {
            if (!string.IsNullOrEmpty(tableBuff.EffectOn) && !string.IsNullOrEmpty(tableBuff.EffectOnBone))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        bool IsBuffHasEffectOff()
        {
            if (!string.IsNullOrEmpty(tableBuff.EffectOff) && !string.IsNullOrEmpty(tableBuff.EffectOffBone))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        bool IsBuffHasEffectHit()
        {
            if (!string.IsNullOrEmpty(tableBuff.HitEffect) && !string.IsNullOrEmpty(tableBuff.HitEffectBone))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        bool IsBuffHasEffectLast()
        {
            if (!string.IsNullOrEmpty(tableBuff.LastEffect) && !string.IsNullOrEmpty(tableBuff.LastEffectBone))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }
}
